'use strict';
var vk; // 全局vk实例
// 涉及的表名
const dbName = require("../../dao/config.js");

var db = uniCloud.database(); // 全局数据库引用
var _ = db.command; // 数据库操作符
var $ = _.aggregate; // 聚合查询操作符

// 设置哪个平台使用VksPay支付，可选：h5、mp-weixin、app-plus、mp-alipay等uniapp条件编译的平台
// 后续会把此变量存到数据库里，可在admin中动态控制，目前先写在此变量中
const useVkspayPlatformList = []; // ["h5", "mp-weixin", "app-plus"];

/**
 * 权限注意：
 * pub_ 开头的函数不需要登录即可访问 如：pub_getList
 * kh_ 开头的函数需要登录才能访问 如：kh_getList
 * sys_ 开头的函数需要授权指定权限才能访问 如：sys_getList
 * _ 开头的函数禁止前端访问 如：_before
 * 其他函数 默认均需要登录才能访问 如：getList（若将云对象文件放在pub目录下，则默认其他函数不需要登录即可访问，若放在sys目录下，则默认其他函数需要授权才能访问）
 */
var cloudObject = {
	isCloudObject: true, // 标记为云对象模式
	/**
	 * 请求前处理，主要用于调用方法之前进行预处理，一般用于拦截器、统一的身份验证、参数校验、定义全局对象等。
	 */
	_before: async function() {
		vk = this.vk; // 将vk定义为全局对象
		// let { customUtil, uniID, config, pubFun } = this.getUtil(); // 获取工具包
	},
	/**
	 * 请求后处理，主要用于处理本次调用方法的返回结果或者抛出的错误
	 */
	_after: async function(obj) {
		let { err, res } = obj;
		if (err) {
			return; // 如果方法抛出错误，直接return;不处理
		}
		return res;
	},
	/**
	 * 创建订单，预创建订单(查价格)
	 * @url client/order.createOrder 前端调用的url参数地址
	 */
	createOrder: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			address_id, // 地址id
			cart_list = [], // 购物车信息 {sku_id: '001-001', buy_num: 1, goods_id: '001'}
			buyer_remark, // 下单人备注
			used_coupon_id, // 优惠券id
			used_vip, // vip会员id
			used_integral, // 使用积分数量 true代表自动计算
			delivery_mode = 0, // 交货方式 0 快递（需配送） 1 到付（需配送） 2 自提（无需配送）
			add_key = false, // 是否下单 false 只查询价格 true 下单
			calc_optimal = false, // 是否需要计算最优方案
			mode = "cart", // cart购物车 buy 直接下单
			used_balance = 0, // 使用多少余额
			delivery_shop_id, // 上门自提的门店id（仅delivery_mode=2时有效）
			location, // 用户的定位信息（仅delivery_mode=2时有效）
			mobile, // 我的手机号（仅delivery_mode=2时有效）
		} = data;
		if (add_key) calc_optimal = false; // 如果是下单模式，则不需要计算最优方案（用户可能已经自己选择了想要的方案）
		if (vk.pubfn.isNull(cart_list)) {
			return { code: -3, msg: '请先添加商品' }
		}
		// 如果使用积分，则提前判断下积分余额是否足够，真实下单时还会再判断
		if (used_integral > 0 && userInfo.account_integral.balance < used_integral) {
			return { code: -4, msg: `积分余额不足，当前余额: ${userInfo.account_integral.balance}` };
		}
		let nowTime = Date.now(); // 当前时间
		let sku_ids = []; // 记录购买的 sku_id 列表
		let sku_nums = {}; // 记录每个 sku_id 购买的数量
		for (let i in cart_list) {
			let item = cart_list[i];
			item.buy_num = parseInt(item.buy_num); //强制转为整数
			if (item.buy_num > 0) {
				sku_ids.push(item.sku_id);
				sku_nums[item.sku_id] = item.buy_num;
			}
		}
		if (sku_ids.length > 30) {
			// 此值理论上最大可以增大到500，但为了响应速度（性能），建议不要修改。
			return { code: -1, msg: '购物车内商品种类不能超过30个' };
		}
		let order_type = 0; // 0 实物商品订单(需要物流) 1 虚拟商品订单(无需物流,有核销码)
		let needExpress = true; // 是否需要快递配送
		let orderTypeIs0 = false;
		let orderTypeIs1 = false;
		let defaultShopInfo;
		// 根据 sku_ids 获取商品sku列表
		let sku_list = await vk.daoCenter.goodsDao.findSkuListByskuIds(sku_ids);
		for (let i in sku_ids) {
			let skuInfo = vk.pubfn.getListItem(sku_list, "_id", sku_ids[i]);
			if (vk.pubfn.isNull(skuInfo)) {
				return { code: -1, msg: `商品编号：${sku_ids[i]}不存在，请清空购物车后重试！` }
			}
			if (!skuInfo.goodsInfo.is_on_sale) {
				return { code: -1, msg: `商品：【${skuInfo.goodsInfo.name}】已下架！` }
			}
			if (skuInfo.goodsInfo.type == 0) {
				orderTypeIs0 = true;
			} else if (skuInfo.goodsInfo.type == 1) {
				orderTypeIs1 = true;
			}
		}
		if (orderTypeIs0 && orderTypeIs1) {
			// 前端已禁用虚拟商品的加入购物车功能，云函数这里是再上一道保险。
			return { code: -5, msg: `实物商品不可以和卡券商品一起下单，请先删除卡券商品或实物商品。` }
		}
		if (orderTypeIs1) {
			order_type = 1;
			needExpress = false; // 无需快递配送
		}
		let deliveryShopInfo;
		// 如果是上门自提，则无需快递配送
		if (delivery_mode === 2) {
			if (!add_key && !delivery_shop_id) {
				// 自动选择最近的门店地址
				if (vk.pubfn.isNullOne(location, location.longitude, location.latitude)) {
					return { code: -1, msg: "请先开启定位" };
				}
				defaultShopInfo = await vk.daoCenter.mchShopDao.getClosestShopInfo({
					longitude: location.longitude, // 经度
					latitude: location.latitude, // 纬度
				});
				if (vk.pubfn.isNull(defaultShopInfo)) {
					return { code: -1, msg: "商家未设置自提门店" };
				}
				delivery_shop_id = defaultShopInfo._id;
			}
			if (add_key && vk.pubfn.isNull(mobile)) {
				return { code: -1, msg: "请输入手机号" };
			}
			if (vk.pubfn.isNull(delivery_shop_id)) {
				return { code: -1, msg: "请选择自提门店" };
			}
			deliveryShopInfo = await vk.daoCenter.mchShopDao.findById(delivery_shop_id);
			if (vk.pubfn.isNull(deliveryShopInfo)) {
				return { code: -1, msg: "您选择的自提门店不存在" };
			}
			needExpress = false; // 无需快递配送
		}
		let buy_num = 0; // 订单总购买数量
		// 设置对应sku的购买数量等信息
		for (let i in sku_list) {
			let goodsInfo = sku_list[i].goodsInfo;
			sku_list[i].buy_num = sku_nums[sku_list[i]._id]; // 购买数量
			sku_list[i].reward_rule = goodsInfo.reward_rule; // 奖励规则
			sku_list[i].integral_rule = goodsInfo.integral_rule; // 积分规则
			sku_list[i].category_ids = goodsInfo.category_ids; // 分类
			sku_list[i].sku_id = sku_list[i]._id; // sku_id
			sku_list[i].send_num = 0; // 设置已发货数量
			sku_list[i].refund_num = 0; // 设置已退款数量
			sku_list[i].refund_amount = 0; // 设置已退款金额
			sku_list[i].give_integral = 0; // 设置赠送积分数量
			sku_list[i].refund_give_integral = 0; // 设置积分退回数量（因退款而扣除的数量）
			sku_list[i].used_integral = 0; // 设置使用的积分数量
			sku_list[i].refund_used_integral = 0; // 设置退回使用积分数量
			buy_num += sku_list[i].buy_num;
			if (orderTypeIs1) {
				sku_list[i].verify_num = 0; // 设置已核销的数量
				// 设置可核销的时间
				let verify_start_time = 0;
				let verify_exp_time = 0;
				if (goodsInfo.exp_time_mode === 1) {
					verify_start_time = goodsInfo.exp_time_range[0];
					verify_exp_time = goodsInfo.exp_time_range[1];
				} else if (goodsInfo.exp_time_mode === 2) {
					verify_start_time = vk.pubfn.getOffsetTime(nowTime, {
						day: goodsInfo.exp_time_rule[0],
						mode: "after", // after 之后 before 之前
					});
					verify_exp_time = vk.pubfn.getOffsetTime(nowTime, {
						day: goodsInfo.exp_time_rule[1],
						mode: "after", // after 之后 before 之前
					});
				}
				sku_list[i].verify_start_time = verify_start_time;
				sku_list[i].verify_exp_time = verify_exp_time;
			}
		}
		let addressInfo;
		if (needExpress) {
			// 如果需要快递配送，则获取收货地址信息
			if (vk.pubfn.isNull(address_id)) {
				// 尝试获取默认收货地址
				addressInfo = await vk.daoCenter.userDao.getDefaultAddress(uid);
			} else {
				// 根据address_id获取收货地址
				addressInfo = await vk.daoCenter.userDao.getAddressById(address_id, uid);
			}
			if (vk.pubfn.isNull(addressInfo)) {
				return { code: -2, msg: `请先选择收货地址！` }
			}
		}
		let mchInfo = await vk.daoCenter.mchDao.find();
		if (vk.pubfn.isNull(mchInfo)) {
			return { code: -1, msg: `未找到商家信息！` }
		}
		// 生成订单号（无数据库请求，性能高，通过数据库唯一索引方式控制绝对不会重复）
		let order_no = vk.pubfn.createOrderNo("DD");
		// 初始化金额信息（单位分 100 = 1元）
		let amountInfo = {
			total_amount: 0, // 订单总金额（商品总金额（原价）+实际运费）
			goods_amount: 0, // 商品总金额（原价）（不含运费）
			original_express_amount: 0, // 原始运费
			express_amount: 0, // 实际运费（如原始运费6元，会员包邮，则实际运费为0元）
			should_payment_amount: 0, // 订单应付金额（应付金额为优惠后的金额）
			payment_amount: 0, // 订单实付金额
			need_payment_amount: 0, // 还需要付款金额
			used_balance_amount: 0, // 订单使用余额付款金额
			used_cash_amount: 0, // 订单使用现金付款金额
			give_integral: 0, // 奖励积分数量
			used_integral: 0, // 使用积分数量
			refund_amount: 0, // 订单退款金额
			refund_balance_amount: 0, // 退回余额
			refund_cash_amount: 0, // 退回现金
			refund_express_amount: 0, // 退款运费金额
			refund_give_integral: 0, // 退回奖励的积分数量
			refund_used_integral: 0, // 退回使用积分数量
		};
		// 初始化订单信息
		let orderInfo = {
			amount_info: amountInfo,
			weight: 0, // 订单重量 1 = 1KG
			status: 0, // 订单状态 : 等待付款
			user_id: uid, // 订单购买者用户id
			inviter_uid: userInfo.inviter_uid, // 邀请人uid，按层级从下往上排列的uid数组，即第一个是直接上级
			// buyer_info 为冗余字段
			buyer_info: {
				_id: uid,
				nickname: userInfo.nickname, // 订单购买者昵称
				avatar: userInfo.avatar, // 订单购买者的头像地址
			},
			order_type, // 订单类型 0:实物商品订单（需要物流） 1:虚拟商品订单（无需物流）
			order_no: order_no, // 订单号(25位),如 DD20200919094200123456789
			buyer_remark: buyer_remark, // 买家备注
			goods_sku_list: sku_list, // 商品sku列表（冗余字段）
			discount_info: {
				total_discount: 0
			},
			auto_cancel_time: nowTime + 1000 * 60 * vk.pubfn.getData(mchInfo, "order.auto_cancel", 60), // 默认订单自动取消时间为1小时后
			update_time: 0,
			delivery_mode, // 交货方式 0 快递（需配送） 1 到付（需配送） 2 自提（无需配送）
			// 订单时间线
			timeline: [
				{ time: nowTime, msg: "下单成功", type: "create", oper_type: "my", oper_uid: uid }
			],
			fx: {
				mode: vk.pubfn.getData(mchInfo, "fx.mode"),
				settlement_status: 0, // 0 未结算 1 已结算 2 不结算
			},
			buy_num,
		};

		let stock_msg = ""; // 库存不足时的提示语
		/**
		 * 判断商品库存是否足够（第一次判断库存）
		 * 计算商品重量
		 * 计算每个sku商品合计(原价)
		 * 计算订单商品合计(原价)
		 */
		for (let i in sku_list) {
			let skuInfo = sku_list[i];
			// 判断库存
			if (add_key && skuInfo.stock < skuInfo.buy_num) {
				stock_msg = `商品（${skuInfo.goods_name} - ${skuInfo.sku_name}）库存不足！当前库存：${skuInfo.stock}`;
				break;
			}
			// 计算重量
			if (skuInfo.weight) {
				orderInfo.weight += skuInfo.weight * skuInfo.buy_num;
			}
			// 计算该sku商品商品原价合计 = 购买数量 * 商品单价（原价）
			skuInfo.total_amount = skuInfo.buy_num * skuInfo.price;
			// 先设置该sku商品的应付金额 = 商品原价合计金额
			skuInfo.should_payment_amount = skuInfo.total_amount;
			// 商品总金额（原价） 单位分 100 = 1元  累加每个sku的total_amount
			amountInfo.goods_amount += skuInfo.total_amount;
		}
		// 第一次判断库存是否足够,实际下单的时候需要使用数据库判断,先扣库存,再生成订单
		if (stock_msg) {
			return { code: -1, msg: stock_msg }
		}
		// 设置订单总重量(保留3位小数)
		orderInfo.weight = vk.pubfn.toDecimal(orderInfo.weight, 3);

		// 计算运费 开始 -----------------------------------------------------------
		let freightsInfoRes = await this._calcFreights({
			needExpress,
			addressInfo,
			weight: orderInfo.weight,
			sku_list,
			add_key
		});
		if (freightsInfoRes.code !== 0) {
			// 返回错误信息
			return freightsInfoRes;
		}
		// 设置收货地址信息
		orderInfo.express_info = freightsInfoRes.express_info;
		// 设置运费金额
		amountInfo.original_express_amount = freightsInfoRes.express_amount;
		amountInfo.express_amount = freightsInfoRes.express_amount;
		if (delivery_mode === 1) {
			// 使用物流到付
			orderInfo.seller_note = `使用物流到付，原快递费用是：${vk.pubfn.priceFilter(amountInfo.express_amount)}元`;
			amountInfo.express_amount = 0;
		} else if (delivery_mode === 2) {
			// 到店自提
			orderInfo.express_info = {
				position: deliveryShopInfo.position,
				formatted_address: deliveryShopInfo.position.formatted_address,
				mode: 0,
				receiver_name: userInfo.nickname,
				receiver_mobile: mobile,
				send_name: deliveryShopInfo.name,
				send_mobile: deliveryShopInfo.service_mobile,
				express_name: "自提"
			};
		}
		// 计算运费 结束-----------------------------------------------------------

		// 计算订单总金额 (商品总金额+运费)（原价） 单位分 100 = 1元
		amountInfo.total_amount = amountInfo.goods_amount + amountInfo.express_amount;
		// 获取我的可用优惠券列表
		let couponList = await vk.daoCenter.userCouponDao.getCouponListByUserId({
			user_id: uid,
			status: 0
		});
		let calcBestDiscountRes; // 最优惠方案
		if (calc_optimal) {
			// 计算最优优惠方案开始 -----------------------------------------------------------
			//console.time("calcBestDiscount");
			calcBestDiscountRes = this._calcBestDiscount({
				sku_ids,
				sku_list,
				userInfo,
				mchInfo,
				couponList,
				original_express_amount: amountInfo.original_express_amount,
			});
			used_vip = calcBestDiscountRes.used_vip;
			used_coupon_id = calcBestDiscountRes.used_coupon_id;
			couponList = calcBestDiscountRes.couponList;
			used_integral = calcBestDiscountRes.used_integral;
			//console.timeEnd("calcBestDiscount");
			// 计算最优优惠方案结束 -----------------------------------------------------------
		}
		// 计算会员价 开始 -----------------------------------------------------------
		//console.time("calcVipPrice");
		if (vk.pubfn.isNotNull(used_vip) && used_vip !== false) {
			let vipPriceInfoRes = this._calcVipPrice({
				used_vip,
				sku_list,
				userInfo,
				mchInfo,
				original_express_amount: amountInfo.original_express_amount,
			});
			if (vipPriceInfoRes.code !== 0) {
				// 返回错误信息
				return vipPriceInfoRes;
			}
			sku_list = vipPriceInfoRes.sku_list; // 更新sku_list
			used_vip = vipPriceInfoRes.used_vip; // 设置最终使用的那个vip
			orderInfo.discount_info.used_vip_name = vipPriceInfoRes.used_vip_name;
			orderInfo.discount_info.vip_discount_amount = vipPriceInfoRes.vip_discount_amount; // 设置订单会员价总优惠金额
			if (vipPriceInfoRes.vip_discount_express_amount) {
				orderInfo.discount_info.vip_discount_express_amount = vipPriceInfoRes.vip_discount_express_amount; // 设置运费抵扣金额
				amountInfo.express_amount -= vipPriceInfoRes.vip_discount_express_amount;
			}
		}
		//console.timeEnd("calcVipPrice");
		// 计算会员价 结束 -----------------------------------------------------------

		// 计算优惠券优惠 开始 -----------------------------------------------------------
		if (vk.pubfn.isNotNull(used_coupon_id)) {
			//console.time("calcCouponPrice");
			let couponPriceInfoRes = this._calcCouponPrice({
				used_coupon_id,
				sku_list,
				sku_ids,
				userInfo,
				used_discount_key: used_vip ? true : false,
				couponList
			});
			if (couponPriceInfoRes.code !== 0) {
				// 返回错误信息
				return couponPriceInfoRes;
			}
			sku_list = couponPriceInfoRes.sku_list; // 更新sku_list
			used_coupon_id = couponPriceInfoRes.used_coupon_id; // 设置最终使用的那张优惠券id
			orderInfo.discount_info.used_coupon_name = couponPriceInfoRes.used_coupon_name; // 设置最终使用的那张优惠券的名称
			orderInfo.discount_info.coupon_discount_amount = couponPriceInfoRes.coupon_discount_amount; // 设置订单优惠券总优惠金额
			//console.timeEnd("calcCouponPrice");
		}
		// 计算优惠券优惠 结束 -----------------------------------------------------------

		// 计算积分优惠 开始 -----------------------------------------------------------
		if (vk.pubfn.isNotNull(used_integral)) {
			//console.time("calcIntegralPrice");
			let integralPriceInfoRes = this._calcIntegralPrice({
				used_integral,
				sku_list,
				userInfo,
				mchInfo,
				used_vip: used_vip ? true : false,
				used_coupon: used_coupon_id ? true : false,
			});
			if (integralPriceInfoRes.code !== 0) {
				// 返回错误信息
				return integralPriceInfoRes;
			}
			// 如果用户传的使用积分数量 > 实际计算可用的积分数量，则需要进行提示
			if (add_key && used_integral > integralPriceInfoRes.used_integral) {
				return { code: -4, msg: `您选择的优惠方案最多只能使用 ${integralPriceInfoRes.used_integral} 积分` };
			}
			sku_list = integralPriceInfoRes.sku_list; // 更新sku_list
			used_integral = integralPriceInfoRes.used_integral; // 设置最终使用积分数量
			orderInfo.amount_info.used_integral = integralPriceInfoRes.used_integral; // 设置最终使用积分数量
			orderInfo.discount_info.integral_discount_amount = integralPriceInfoRes.discount_amount; // 设置订单积分总优惠金额
			//console.timeEnd("calcIntegralPrice");
		}
		// 计算积分优惠 结束 -----------------------------------------------------------

		// 先设置订单应付金额 = 订单总金额,再减去优惠金额
		amountInfo.should_payment_amount = amountInfo.total_amount;

		// 计算应付金额 = 订单总金额 - 优惠抵扣金额
		for (let k in orderInfo.discount_info) {
			if (k.indexOf("_discount_amount") > -1 ||
				k.indexOf("_discount_express_amount") > -1) {
				let v = orderInfo.discount_info[k];
				if (v !== 0) {
					amountInfo.should_payment_amount -= v;
					orderInfo.discount_info.total_discount += v;
				}
			}
		}
		orderInfo.discount_info.used_vip = used_vip;
		orderInfo.discount_info.used_coupon_id = used_coupon_id;
		// 订单还需要付款的金额 = 订单应付金额 - 订单实付金额(已付金额) = should_payment_amount - payment_amount
		amountInfo.need_payment_amount = amountInfo.should_payment_amount - amountInfo.payment_amount;
		if (amountInfo.need_payment_amount < 0) {
			return { code: -1, msg: "参数错误!" };
		}
		// 赋值金额信息
		orderInfo.amount_info = amountInfo;
		// 计算每个sku的实际单价 = 应付金额 / 购买数量
		for (let i = 0; i < sku_list.length; i++) {
			sku_list[i].real_price = vk.pubfn.toDecimal(sku_list[i].should_payment_amount / sku_list[i].buy_num, 0);
		}
		// 计算订单实际折扣 0.5 代表 5折
		orderInfo.discount_info.real_discount = vk.pubfn.toDecimal((orderInfo.amount_info.should_payment_amount - orderInfo.amount_info.express_amount) / orderInfo
			.amount_info.goods_amount, 2)

		// 计算本订单可以获得多少积分
		let giveIntegral = await vk.daoCenter.orderDao.calcGiveIntegral({
			mchInfo,
			userInfo,
			goods_list: sku_list,
			update: true, // 是否会更新goods_list内的give_integral
		});
		orderInfo.amount_info.give_integral = giveIntegral; // 设置订单奖励积分数量

		// 如果是下单,则需要扣除库存
		if (add_key) {
			// 判断限购规则
			for (let i = 0; i < sku_list.length; i++) {
				let skuItem = sku_list[i];
				let { buy_num, goodsInfo } = skuItem;
				let { limit_buy_rule = {}, name, _id: goods_id } = goodsInfo;
				let { every_day_limit_num = 0, activity_limit_num = 0, limit_time } = limit_buy_rule;
				// 常规每日限购
				if (every_day_limit_num > 0) {
					let { todayStart, todayEnd } = vk.pubfn.getCommonTime();
					let num = await vk.daoCenter.orderDao.getUserBuyNumByGoodsId({
						user_id: uid,
						_add_time: _.gte(todayStart).lte(todayEnd),
						status: _.nin([-4, -3, -1]),
						goods_id,
					});
					console.log('num: ', num)
					if ((num + buy_num) > every_day_limit_num) return { code: -6, msg: `下单失败：商品【${name}】每日限购【${every_day_limit_num}】个（含已下单未付款订单）` };
				}
				let time = Date.now();
				// 活动期间内总限购
				if (activity_limit_num > 0) {
					if (!limit_time) limit_time = [];
					let startTime = limit_time[0] || 0;
					let endTime = limit_time[1] || Number.MAX_VALUE;
					if (time < startTime) return { code: -1, msg: `下单失败：请在【${vk.pubfn.timeFormat(startTime)}】之后购买` };
					if (time > endTime) return { code: -1, msg: `下单失败：活动已结束，结束时间：${vk.pubfn.timeFormat(endTime)}` };
					let num = await vk.daoCenter.orderDao.getUserBuyNumByGoodsId({
						user_id: uid,
						_add_time: _.gte(startTime).lte(endTime),
						status: _.nin([-4, -3, -1]),
						goods_id,
					});
					if ((num + buy_num) > activity_limit_num) return { code: -6, msg: `下单失败：商品【${name}】活动期间内累计限购【${activity_limit_num}】个（含已下单未付款订单）` };
				}
			}

			// 真实扣库存（不使用事务，用事务会有并发扣库存导致报错的问题）
			let updateSkuStockRes = await vk.daoCenter.goodsDao.updateSkuStockByskuList({
				list: sku_list,
			});
			// 如果库存不足，则直接返回错误信息
			if (updateSkuStockRes.code !== 0) {
				return updateSkuStockRes;
			}
			// 去除goods_sku_list数组中的goodsInfo，没有必要将它也保存到数据库
			for (let i in orderInfo.goods_sku_list) {
				delete orderInfo.goods_sku_list[i].goodsInfo;
			}

			// 开启事务（保证下单、扣积分、扣优惠券为一个事务内的原子操作）
			let transaction = await vk.baseDao.startTransaction();
			let order_id;
			try {
				// 如果用了积分，则扣除积分
				if (used_integral > 0) {
					// 扣积分
					let upReq = await vk.daoCenter.moneyDao.updateAccountIntegralForTransaction({
						db: transaction,
						user_id: uid,
						value: used_integral,
						isAdd: false, // true 增加 false 减少
						no: order_no,
						title: `使用积分抵扣订单金额`,
						comment: ``,
						add_type: 3, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
					});
				}
				// 真实生成订单 - 添加订单到数据库
				order_id = await vk.daoCenter.orderDao.add({
					db: transaction,
					dataJson: orderInfo
				});
				// 如果用了优惠券，则将优惠券设置为已使用
				if (vk.pubfn.isNotNull(used_coupon_id)) {
					// 将优惠券设置为已使用
					let updateNum = await vk.daoCenter.userCouponDao.updateMyCouponsById(used_coupon_id, uid, transaction);
					if (updateNum <= 0) {
						throw new Error(JSON.stringify({ code:-1, msg:"优惠券使用失败，请重试"}));
					}
					// uniCloud.logger
					console.log("将优惠券设置为已使用:", {
						updateNum,
						order_no,
						used_coupon_id
					});
				}
				// 提交事务
				await transaction.commit();
				console.log(`transaction succeeded`);
			} catch (err) {
				// 事务回滚
				let errCode = -1;
				if (err && err.message && err.message.indexOf("余额不足")>-1){
					errCode = -4;
				}
				return await vk.baseDao.rollbackTransaction({
					db: transaction,
					err,
					code: errCode
				});
			}
			orderInfo._id = order_id;
			// 如果是以购物车方式购买，则删除已下单的购物车内的商品（因批量操作，故不使用事务）
			if (mode === "cart") {
				await vk.daoCenter.cartDao.del({
					user_id: uid,
					sku_id: _.in(sku_ids)
				});
			}

			// 判断是否使用余额，如果是，则进行一次余额付款操作
			if (used_balance > 0 || amountInfo.need_payment_amount === 0) {
				// 进行余额付款（余额付款会开始第二个事务，即下单成功和余额付款是2个独立的事务）
				await this.balancePay({
					_id: order_id, // 订单id
					used_balance: used_balance, // 使用余额数量
				});
			}
		}
		// 返回给前端的数据
		let res = {
			code: 0,
			msg: "ok",
			order_no: orderInfo.order_no, // 订单号
			isVip: userInfo.vip_lv > 0 ? true : false, // 是否是vip用户
			addressInfo, // 地址信息
			needExpress, // 是否需要配送
			user_account_balance: userInfo.account_balance.balance, // 当前用户钱包余额
			used_coupon_id, // 用户使用的优惠券id
			used_vip, // 是否使用会员优惠
			used_integral, // 使用积分数量
			couponList: !add_key ? couponList : undefined, // 我当前可用的优惠券列表
			calc_optimal, // 是否使用最优惠方案
			orderInfo, // 订单详情
			giveIntegral, // 赠送多少积分
			shopInfo: defaultShopInfo, // 上门自提时门店信息
		};
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 计算运费
	 */
	_calcFreights: async function(obj) {
		let {
			needExpress,
			addressInfo,
			weight,
			sku_list,
			add_key
		} = obj;
		let express_info = {}; // 收货地址信息
		let express_amount = 0; // 最终运费
		if (needExpress && vk.pubfn.isNotNull(addressInfo)) {
			// 如果一个订单包含的商品有多个运费模板，则首费取最高档，增费求和，其他首费减半。
			let expressIdGroup = {}; // 运费id分组求重量
			let freightIds = []; // 本次订单涉及到的运费模板id列表
			sku_list.map((item, index) => {
				let { is_free_delivery, freight_id } = item.goodsInfo;
				// 只有非包邮商品，且有设置运费模板id的商品才需要计算运费
				if (!is_free_delivery && freight_id) {
					if (!expressIdGroup[freight_id]) {
						expressIdGroup[freight_id] = {
							weight: 0,
							goods: []
						}
					}
					expressIdGroup[freight_id].weight += (item.weight * item.buy_num);
					expressIdGroup[freight_id].goods.push(item.goodsInfo.name);
					freightIds.push(freight_id);
				}
			});
			// 去重复
			freightIds = [...new Set(freightIds)];
			if (vk.pubfn.isNotNull(freightIds)) {
				// 从数据库中获取本次订单涉及到的运费模板列表
				let freightList = await vk.daoCenter.freightDao.select({
					pageIndex: 1,
					pageSize: freightIds.length,
					getMain: true,
					whereJson: {
						_id: _.in(freightIds)
					}
				});
				let province_code = addressInfo.position.province.code; // 用户收货地址中的省id
				let reality_first_weight_amount = 0;
				let reality_continuous_weight_amount = 0;
				let first_weight_id;
				let first2continuous = {};
				for (let i in expressIdGroup) {
					let { weight, goods } = expressIdGroup[i];
					let freightInfo = vk.pubfn.getListItem(freightList, "_id", i);
					let { freight_rules } = freightInfo;
					let freightItem = freight_rules.find((item) => {
						return item.province_codes.indexOf(province_code) > -1;
					});
					if (vk.pubfn.isNull(freightItem)) {
						// 如果为空，则提示不支持配送，无法下单。
						return { code: -1, msg: `商品【${goods[0]}】不支持您所选择的地区【${addressInfo.position.province.name}】配送，请更换收货地址！` }
					}
					// 设置重量达到此值时，会多计算首重的价格，并少一次续重的价格 倍乘（相当于拆分多个包裹）
					freightItem.max_weight = freightInfo.max_weight;
					// 计算运费
					let freightRes = vk.pubfn.calcFreightDetail(freightItem, weight);
					let {
						first_weight_amount, // 首重总金额
						continuous_weight_amount, // 续重总金额
					} = freightRes;
					// 首重费用取最大，同时其他的首重费用要变成续重
					if (first_weight_amount > reality_first_weight_amount) {
						reality_first_weight_amount = first_weight_amount;
						first_weight_id = i; // 记录哪个运费模板id计算的首重最高，非最高的首重减半
					}
					// 续重费用求和
					reality_continuous_weight_amount += continuous_weight_amount;
					// 首重费用减半
					first2continuous[i] = vk.pubfn.toDecimal(first_weight_amount / 2, 0);
				}
				express_amount = reality_first_weight_amount + reality_continuous_weight_amount;
				// 将非最高首重的运费模板的首重减半后，增加到实际运费中
				for (let i in first2continuous) {
					if (i !== first_weight_id && first2continuous[i] > 0) {
						express_amount += first2continuous[i];
					}
				}
				// 最终运费取整
				express_amount = vk.pubfn.toDecimal(express_amount, 0);
				if (express_amount < 0) {
					return { code: -1, msg: '运费计算错误' }
				}
			}
			// 记录收货地址信息
			express_info = {
				position: addressInfo.position, // 地址的省市区+街道信息
				formatted_address: addressInfo.formatted_address,
				mode: 1,
				receiver_name: addressInfo.name,
				receiver_mobile: addressInfo.mobile
			};
		}
		let res = {
			code: 0,
			msg: "ok",
			express_amount, // 运费
			express_info, // 收货地址信息
		};
		return res;
	},
	/**
	 * 计算最优优惠组合方案（无数据库请求）
	 * 2023-05-13 升级算法，支持会员折扣、优惠券、积分
	 */
	_calcBestDiscount: function(obj) {
		let {
			sku_ids, // 商品sku id数组
			sku_list, // 商品sku信息
			userInfo, // 下单人用户信息
			mchInfo, // 商户信息
			couponList = [], // 优惠券列表
			original_express_amount, // 订单运费
		} = obj;
		let used_vip = true; // 最终是否使用会员优惠
		let used_coupon_id; // 最终使用优惠券的id
		let used_integral = 0; // 最终使用积分的数量
		let finalTotalDiscountAmount = 0; // 最终总优惠金额

		let discountCombinations = []; // 所有优惠组合

		// 会员折扣的使用情况：0表示不使用，1表示使用
		for (let i = 0; i <= 1; i++) {
			// 优惠券的使用情况：0表示不使用，1到couponList.length表示使用不同的优惠券
			for (let j = 0; j <= couponList.length; j++) {
				// 积分的使用情况：0表示不使用，1表示使用
				for (let k = 0; k <= 1; k++) {
					let totalDiscountAmount = 0; // 当前组合的总优惠金额
					let vipDiscountAmount = 0; // 当前组合的会员优惠金额
					let couponDiscountAmount = 0; // 当前组合的优惠优惠金额
					let integralDiscountAmount = 0; // 当前组合的积分优惠金额
					let usedIntegral = 0; // 使用积分数量
					let new_sku_list = vk.pubfn.copyObject(sku_list); // 拷贝一份sku数据，防止污染原数据
					let coupon;
					// 开始计算
					if (i === 1) {
						// 计算会员优惠
						let vipPriceInfoRes = this._calcVipPrice({
							used_vip: true,
							sku_list: new_sku_list,
							userInfo,
							mchInfo,
							original_express_amount
						});
						if (vipPriceInfoRes.code == 0) {
							// 记录会员优惠的金额
							vipDiscountAmount = vipPriceInfoRes.discount_amount || 0;
						}
					}
					if (j > 0) {
						coupon = couponList[j-1]; // 当前优惠券信息
						// 计算优惠券金额
						let couponPriceInfoRes = this._calcCouponPrice({
							used_coupon_id: coupon._id,
							sku_list: new_sku_list,
							sku_ids,
							userInfo,
							used_discount_key: (i === 1 || k === 1) ? true : false,
							couponList
						});
						if (couponPriceInfoRes.code !== 0) {
							// 返回错误信息
							coupon.disabled = true;
							coupon.disabledMsg = couponPriceInfoRes.disabledMsg;
							continue;
						}
						// 记录优惠券抵扣的金额
						couponDiscountAmount = couponPriceInfoRes.discount_amount;
					}

					if (k === 1) {
						// 计算积分优惠
						let integralPriceInfoRes = this._calcIntegralPrice({
							used_integral: true,
							sku_list: new_sku_list,
							userInfo,
							mchInfo,
							used_vip: i === 1 ? true : false,
							used_coupon: j === 1 ? true : false,
						});
						if (integralPriceInfoRes.code == 0) {
							// 记录会员优惠的金额
							integralDiscountAmount = integralPriceInfoRes.discount_amount || 0; // 记录积分优惠金额
							usedIntegral = integralPriceInfoRes.used_integral || 0; // 记录使用积分的数量
						}
					}
					// 计算当前组合总优惠券
					totalDiscountAmount = vipDiscountAmount + couponDiscountAmount + integralDiscountAmount;
					// 记录当前优惠方式
					discountCombinations.push({
						discount_amount: totalDiscountAmount,
						used_vip: i === 1 ? true : false,
						used_coupon_id: j > 0 ? coupon._id : "",
						used_integral: k === 1 ? usedIntegral : 0,
						combination: [i, j, k]
					});
				}
			}
		}

		// 按 discount_amount 排序
		let sortDiscountCombinations = discountCombinations.sort((a, b) => {
			return b.discount_amount - a.discount_amount
		});

		sortDiscountCombinations.map((item, index) => {
			if (index === 0) {
				// 第一个就是最优惠的组合
				used_vip = item.used_vip;
				used_coupon_id = item.used_coupon_id;
				used_integral = item.used_integral;
			}
			console.log(`组合${index+1}`,item.combination,`共优惠金额：${vk.pubfn.toDecimal(item.discount_amount/100, 2)} 元`, index === 0 ? "（最优惠）" : "");
		});
		return {
			couponList, // 优惠券列表
			used_vip, // 最终是否使用会员优惠
			used_coupon_id, // 最终使用优惠券的id
			used_integral, // 最终使用积分的数量
		};
	},

	/**
	 * 计算订单会员价（无数据库请求）
	 */
	_calcVipPrice: function(obj) {
		let order_used_vip_key = false; // 是否使用 vip 优惠
		let vip_discount_amount = 0; // vip 优惠订单金额
		let vip_discount_express_amount = 0; // vip 优惠运费金额
		let used_vip_name;
		let {
			used_vip,
			sku_list,
			userInfo,
			mchInfo,
			original_express_amount,
		} = obj;
		let myVipLv = userInfo.vip_lv;
		if (used_vip === true) {
			used_vip = myVipLv;
		}
		if (vk.pubfn.isNotNull(used_vip)) {
			let vipInfo;
			// 根据used_vip 查询折扣信息
			if (typeof used_vip !== "string") {
				// 会员等级
				if (myVipLv !== used_vip) {
					return { code: -1, msg: "您没有该会员等级或会员卡！" };
				}
				let { vip_level_rule = [] } = mchInfo;
				vipInfo = vk.pubfn.getListItem(vip_level_rule, "lv", used_vip);
			} else {
				// 暂不支持会员权益卡
			}
			if (vk.pubfn.isNotNull(vipInfo)) {
				used_vip_name = vipInfo.name;
				let goods_amount = 0;
				for (let i in sku_list) {
					let skuInfo = sku_list[i];
					let sku_used_vip_key = false; // 该商品是否使用了vip优惠，在还没计算前，设置为false(代表还没使用vip优惠)
					// 该商品没有禁用会员价，才需要进行计算
					if (skuInfo.total_amount >= 0 && !skuInfo.goodsInfo.disable_vip) {
						// 计算当前会员价格 开始 -----------------------------------------------------------
						let vipPriceInfoReq = this._calcVipPriceBySkuInfo({
							used_vip,
							skuInfo,
							vipInfo,
						});
						skuInfo = vipPriceInfoReq.skuInfo;
						// 如果该商品sku使用了会员价
						if (vipPriceInfoReq.sku_used_vip_key) {
							// 增加该订单vip优惠金额
							vip_discount_amount += skuInfo.vip_discount_amount;
							// 设置本订单使用了会员等级(或会员价)
							order_used_vip_key = true;
						}
						sku_list[i] = skuInfo;
						goods_amount += skuInfo.should_payment_amount
						// 计算当前会员价格 结束 -----------------------------------------------------------
					}
				}
				// 运费抵扣
				if (vipInfo.is_free_shipping) {
					if (!vipInfo.free_shipping_min_order_amount || goods_amount >= vipInfo.free_shipping_min_order_amount) {
						vip_discount_express_amount = original_express_amount;
					}
				}
			}
		}
		return {
			code: 0,
			msg: "ok",
			sku_list,
			order_used_vip_key,
			vip_discount_amount,
			vip_discount_express_amount,
			discount_amount: vip_discount_amount + vip_discount_express_amount,
			used_vip,
			used_vip_name
		};
	},
	/**
	 * 计算每个商品的会员价（无数据库请求）
	 */
	_calcVipPriceBySkuInfo: function(obj) {
		let {
			used_vip,
			skuInfo,
			vipInfo = {}
		} = obj;
		let sku_used_vip_key = false; // 该商品是否使用了vip优惠
		let vip_price = skuInfo.total_amount; // 会员价(这里设置默认为商品合计原价)
		let skuVipInfo; // 商品单独的会员价
		if (vk.pubfn.isNotNull(skuInfo.vip_price_rules)) {
			skuVipInfo = vk.pubfn.getListItem(skuInfo.vip_price_rules, "_id", used_vip);
		}
		if (vipInfo.enable !== false) {
			if (vk.pubfn.isNotNull(skuVipInfo)) {
				// 计算独立会员价
				if (skuVipInfo.is_fixed_calc) {
					// 特价优惠(固定价格)
					vip_price = skuInfo.buy_num * skuVipInfo.fixed_value;
				} else {
					// 打折优惠(百分比价格)
					vip_price = skuInfo.total_amount * skuVipInfo.proportion_value;
					vip_price = Math.ceil(vip_price); // 向上取整
					if (vip_price < 0) {
						vip_price = 0; // 最低0元
					}
				}
				// 设置该商品sku的vip信息
				skuInfo.vip_info = skuVipInfo;
				sku_used_vip_key = true; // 该商品使用了会员价
			} else if (vk.pubfn.isNotNull(vipInfo.discount)) {
				// 否则使用会员卡本身的默认折扣(如果有默认折扣)
				let vip_discount = vipInfo.discount;
				if (vip_discount > 0 && vip_discount <= 1) {
					// 打折优惠(百分比价格)
					vip_price = skuInfo.total_amount * vip_discount;
					vip_price = Math.ceil(vip_price); // 向上取整
					if (vip_price < 0) {
						vip_price = 0; // 最低0元
					}
					// 设置该商品sku的vip信息
					skuInfo.vip_info = {
						_id: used_vip,
						is_fixed_calc: false,
						proportion_value: vip_discount
					};
					sku_used_vip_key = true; // 该商品使用了会员价
				}
			}
			// 如果该商品sku使用了会员价
			if (sku_used_vip_key) {
				// 设置该商品sku的应付金额
				skuInfo.should_payment_amount = vip_price;
				// 设置该商品sku的vip优惠金额
				skuInfo.vip_discount_amount = skuInfo.total_amount - skuInfo.should_payment_amount;
				// 增加该商品sku的总优惠金额
				if (!skuInfo.total_discount) skuInfo.total_discount = 0;
				skuInfo.total_discount += skuInfo.vip_discount_amount;
			}
		}
		return {
			skuInfo,
			sku_used_vip_key
		};
	},
	/**
	 * 计算优惠券优惠后的价格
	 */
	_calcCouponPrice: function(obj) {
		let {
			used_coupon_id,
			sku_list,
			sku_ids,
			userInfo,
			used_discount_key,
			couponList
		} = obj;
		let coupon_discount_amount = 0;
		let order_used_coupon_key = false; // 该订单是否使用优惠券优惠
		let couponInfo = vk.pubfn.getListItem(couponList, "_id", used_coupon_id);
		if (vk.pubfn.isNull(couponInfo)) {
			return { code: -4, msg: `优惠券不存在或已使用-${used_coupon_id}` };
		}
		let used_coupon_name = couponInfo.couponInfo.name;
		let nowTime = Date.now();
		// 公共条件1 通过status来判断是否可用
		if (couponInfo.status == 1) {
			return { code: -1, msg: `优惠券(${couponInfo.couponInfo.name})已使用!`, disabledMsg: "已使用" };
		}
		if (couponInfo.status == 2) {
			return { code: -1, msg: `优惠券(${couponInfo.couponInfo.name})已过期!`, disabledMsg: "已过期" };
		}
		// 公共条件1 通过start_time和exp_time来判断是否可用
		if (couponInfo.start_time > nowTime) {
			return { code: -1, msg: `优惠券(${couponInfo.couponInfo.name})未到可用时间，需在${vk.pubfn.timeFormat(couponInfo.start_time)}之后才能使用`, disabledMsg: "暂不可用" };
		}
		if (couponInfo.exp_time < nowTime) {
			return { code: -1, msg: `优惠券(${couponInfo.couponInfo.name})已过期!`, disabledMsg: "已过期" };
		}
		// 公共条件2 判断优惠券是否仅限原价购买
		if (couponInfo.couponInfo.only_original_price_use && used_discount_key) {
			return { code: -1, msg: `优惠券(${couponInfo.couponInfo.name})不可与会员价等其他优惠叠加使用!`, disabledMsg: "不可叠加" };
		}
		// 公共条件3 如果有对应的exchange_buy_goods_id字段,需要判断是否订单中是否包含此商品
		if (couponInfo.couponInfo.exchange_buy_goods_id) {
			if (sku_ids.indexOf(couponInfo.couponInfo.exchange_buy_goods_id) == -1) {
				return { code: -1, msg: `优惠券(${couponInfo.couponInfo.name})未满足需购买指定商品的条件`, disabledMsg: "未购指定商品" };
			}
		}
		// 遍历需要购买的sku商品列表,计算出符合优惠券条件的商品
		let coupon_sku_amount_sum = 0; // 可以使用优惠券的sku商品应付金额合计
		let coupon_sku_num = 0; // 可以使用优惠券的sku商品数量合计
		for (let i in sku_list) {
			let skuInfo = sku_list[i];
			let sku_used_coupon_id_key = false; // 该sku商品是否使用了优惠券优惠
			// 如果该sku商品没有禁用优惠券,且用户也使用了优惠券
			if (skuInfo.total_amount >= 0 && !skuInfo.goodsInfo.disable_coupon) {
				// 计算允许用该优惠券的商品合计金额 开始 -----------------------------------------------------------
				let available_range_rule = couponInfo.couponInfo.available_range_rule;
				let coupon_key = false;
				let category_ids = available_range_rule.category_ids;
				let goods_ids = available_range_rule.goods_ids;
				if (available_range_rule.type == 1) {
					// type = 1 代表 指定商品或商品分类可用
					if (available_range_rule.goods_type === 0) {
						// 0 指定分类
						if (vk.pubfn.isNotNull(category_ids)) {
							coupon_key = vk.pubfn.checkArrayIntersection(category_ids, skuInfo.category_ids);
						}
					} else {
						// 1 指定商品
						if (vk.pubfn.isNotNull(goods_ids)) {
							coupon_key = goods_ids.indexOf(skuInfo.goods_id) > -1 ? true : false;
						}
					}
				} else if (available_range_rule.type == 2) {
					// type = 2 代表 指定商品或商品分类不可用

					if (available_range_rule.goods_type === 0) {
						// 0 指定分类
						if (vk.pubfn.isNotNull(category_ids)) {
							coupon_key = !vk.pubfn.checkArrayIntersection(category_ids, skuInfo.category_ids);
						}
					} else {
						// 1 指定商品
						if (vk.pubfn.isNotNull(goods_ids)) {
							coupon_key = goods_ids.indexOf(skuInfo.goods_id) == -1 ? true : false;
						}
					}
				} else if (available_range_rule.type == 0) {
					coupon_key = true;
				}
				if (coupon_key) {
					coupon_sku_num++; // 累计可以使用优惠券的sku商品数量合计
					skuInfo.sku_used_coupon_key = true; // 设置该sku商品使用了优惠券
					order_used_coupon_key = true; // 设置订单使用了优惠券
					coupon_sku_amount_sum += skuInfo.should_payment_amount;
				}
				// 计算允许用该优惠券的商品合计金额 结束 -----------------------------------------------------------
			}
		}

		if (!order_used_coupon_key) {
			return { code: -4, msg: `优惠券[${couponInfo.couponInfo.name}]未满足使用条件`, order_used_coupon_key, disabledMsg: "未满足条件" };
		}
		if (couponInfo.couponInfo.coupon_rule.min_amount > 0 && coupon_sku_amount_sum > 0 &&
			coupon_sku_amount_sum < couponInfo.couponInfo.coupon_rule.min_amount) {
			let min_amount = vk.pubfn.priceFilter(couponInfo.couponInfo.coupon_rule.min_amount);
			return { code: -4, msg: `优惠券[${couponInfo.couponInfo.name}]未满足满减条件，满 ${min_amount} 才可使用`, disabledMsg: `未满${min_amount}元` };
		}

		// 计算共优惠券金额
		if (couponInfo.couponInfo.type === 2) {
			// 打折券
			coupon_discount_amount = Math.round((1 - couponInfo.couponInfo.coupon_rule.discount_proportion) * coupon_sku_amount_sum);
		} else {
			// 满减券
			coupon_discount_amount = couponInfo.couponInfo.coupon_rule.discount_amount;
		}
		if (coupon_discount_amount <= 0) {
			return { code: -1, msg: "优惠券[" + couponInfo.couponInfo.name + "]异常" };
		}
		// console.log(couponInfo.couponInfo.coupon_rule.discount_proportion +" "+ coupon_sku_amount_sum);
		// console.log("共优惠券金额:"+coupon_discount_amount/100);
		// 再次循环一遍,按金额比例均摊优惠金额
		let now_coupon_sku_num = 0;
		let now_sum_coupon_discount_amount = 0;
		for (let i in sku_list) {
			let skuInfo = sku_list[i];
			// 如果该sku商品使用了优惠券
			if (skuInfo.sku_used_coupon_key) {
				now_coupon_sku_num++;
				if (now_coupon_sku_num < coupon_sku_num) {
					// 该sku优惠金额 = 该sku应付金额 / 总应付金额(使用了优惠券的商品) * 总优惠券金额
					skuInfo.coupon_discount_amount = parseInt(skuInfo.should_payment_amount / coupon_sku_amount_sum * coupon_discount_amount);
					// 当前累计已优惠金额
					now_sum_coupon_discount_amount += skuInfo.coupon_discount_amount;
				} else {
					// 最后一个sku的优惠金额 = 总优惠券金额 - 当前累计已优惠金额
					skuInfo.coupon_discount_amount = coupon_discount_amount - now_sum_coupon_discount_amount;
				}
				// 该商品sku的应付价格 = 之前的应付价格 - 现在优惠券优惠的价格
				skuInfo.should_payment_amount -= skuInfo.coupon_discount_amount;
				// 增加该商品sku的总优惠金额
				if (!skuInfo.total_discount) skuInfo.total_discount = 0;
				skuInfo.total_discount += skuInfo.coupon_discount_amount;
				// 记录该商品使用了哪张优惠券ID
				skuInfo.used_coupon_id = used_coupon_id;
				//console.log(skuInfo._id+":"+skuInfo.coupon_discount_amount/100);
				sku_list[i] = skuInfo;
			}
		}

		return {
			code: 0,
			msg: "ok",
			sku_list,
			order_used_coupon_key,
			used_coupon_id,
			used_coupon_name,
			coupon_discount_amount,
			discount_amount: coupon_discount_amount
		};
	},

	/**
	 * 计算订单使用积分优惠后的价格（无数据库请求）
	 * 注意：积分不支持抵扣运费
	 */
	_calcIntegralPrice: function(obj) {
		let order_used_integral_key = false; // 是否使用 积分 优惠
		let integral_discount_amount = 0; // 积分 优惠订单金额
		let {
			used_integral,
			sku_list,
			userInfo,
			mchInfo,
			used_vip, // 是否使用了vip
 			used_coupon, // 是否使用了优惠券
		} = obj;
		let { integral_rule={} } = mchInfo;
		let {
			enable,
			discount_rule={},
			available_range_rule={},
			disable_vip, // 是否禁用会员优惠
			disable_coupon, // 是否禁用优惠券
		} = integral_rule;
		// 只有开启了积分规则，且用户用了积分
		if (enable && used_integral
			// 同时没有禁用会员优惠或没有用会员优惠
			&& (!disable_vip || !used_vip)
			// 以及没有禁用优惠券或没用优惠券
			&& (!disable_coupon || !used_coupon)
		) {
			// 只有启用了积分规则，才能使用积分
			// 遍历需要购买的sku商品列表,计算出符合积分抵扣条件的商品
			let integral_sku_amount_sum = 0; // 可以使用积分的sku商品应付金额合计
			let integral_sku_num = 0; // 可以使用积分的sku商品数量合计
			for (let i in sku_list) {
				let skuInfo = sku_list[i];
				// 计算允许用积分的商品合计金额 开始 -----------------------------------------------------------
				let integral_key = false;
				let category_ids = available_range_rule.category_ids;
				let goods_ids = available_range_rule.goods_ids;
				if (available_range_rule.type == 1) {
					// type = 1 代表 指定商品或商品分类可用
					if (available_range_rule.goods_type === 0) {
						// 0 指定分类
						if (vk.pubfn.isNotNull(category_ids)) {
							integral_key = vk.pubfn.checkArrayIntersection(category_ids, skuInfo.category_ids);
						}
					} else {
						// 1 指定商品
						if (vk.pubfn.isNotNull(goods_ids)) {
							integral_key = goods_ids.indexOf(skuInfo.goods_id) > -1 ? true : false;
						}
					}
				} else if (available_range_rule.type == 2) {
					// type = 2 代表 指定商品或商品分类不可用
					if (available_range_rule.goods_type === 0) {
						// 0 指定分类
						if (vk.pubfn.isNotNull(category_ids)) {
							integral_key = !vk.pubfn.checkArrayIntersection(category_ids, skuInfo.category_ids);
						}
					} else {
						// 1 指定商品
						if (vk.pubfn.isNotNull(goods_ids)) {
							integral_key = goods_ids.indexOf(skuInfo.goods_id) == -1 ? true : false;
						}
					}
				} else if (available_range_rule.type == 0) {
					integral_key = true;
				}
				if (integral_key) {
					order_used_integral_key = true; // 标记该订单使用了积分
					skuInfo.sku_used_integral_key = true; // 设置该sku商品使用了积分
					integral_sku_num++; // 累加使用了积分优惠的商品数量
					integral_sku_amount_sum += skuInfo.should_payment_amount; // 累加使用了积分优惠的商品金额
				}
				// 计算允许用积分的商品合计金额 结束 -----------------------------------------------------------
			}
			if (!order_used_integral_key) {
				return { code: -4, msg: `未满足积分使用条件`, order_used_integral_key, disabledMsg: "未满足条件" };
			}

			// 计算总使用积分 = 向下取整(商品金额 / discount_rule.a) * discount_rule.b
			let sum_used_integral = Math.floor(integral_sku_amount_sum / discount_rule.a) * discount_rule.b;
			let reality_used_integral = sum_used_integral; // 默认用最大可用积分
			// 如果主动设置了用多少积分，且小于sum_used_integral，则更改reality_used_integral = used_integral
			if (typeof used_integral === "number" && used_integral < sum_used_integral) {
				reality_used_integral = used_integral;
			}
			if (userInfo.account_integral.balance < reality_used_integral) {
				// 如果用户积分不足，则以 Math.floor(用户积分 / discount_rule.b) * discount_rule.c
				reality_used_integral = Math.floor(userInfo.account_integral.balance / discount_rule.b) * discount_rule.b;
			}
			// 计算总优惠金额 = 向下取整(reality_used_integral / discount_rule.b) * discount_rule.c
			integral_discount_amount = Math.floor(reality_used_integral / discount_rule.b) * discount_rule.c; // 积分抵扣金额
			used_integral = reality_used_integral; // 记录最终使用积分数量
			// 再次循环一遍,按金额比例均摊优惠金额
			let now_calc_sku_num = 0; // 记录当前算到第一个商品了（因为最后一个商品需要特殊处理）
			let now_calc_discount_amount = 0; // 记录当前已分摊的优惠金额
			let now_calc_use_integral = 0; // 记录当前已标记的积分金额
			for (let i in sku_list) {
				let skuInfo = sku_list[i];
				// 如果该sku商品使用了积分
				if (skuInfo.sku_used_integral_key) {
					now_calc_sku_num++;
					if (now_calc_sku_num < integral_sku_num) {
						// 如果不是最后一个sku
						// 该sku优惠金额 = 该sku应付金额 / 总应付金额(使用了积分的商品) * 总积分金额
						skuInfo.integral_discount_amount = parseInt(skuInfo.should_payment_amount / integral_sku_amount_sum * integral_discount_amount);
						// 当前累计已优惠金额
						now_calc_discount_amount += skuInfo.integral_discount_amount;
						// 该sku使用积分数量 = 该sku应付金额 / 总应付金额(使用了积分的商品) * 总使用积分
						skuInfo.used_integral = parseInt(skuInfo.should_payment_amount / integral_sku_amount_sum * used_integral);
						// 当前累加使用积分
						now_calc_use_integral += skuInfo.used_integral;
					} else {
						// 最后一个sku的优惠金额 = 总积分金额 - 当前累计已优惠金额
						skuInfo.integral_discount_amount = integral_discount_amount - now_calc_discount_amount;
						// 最后一个sku使用的积分 = 总使用积分 - 当前累计已使用的积分
						skuInfo.used_integral = used_integral - now_calc_use_integral;
					}
					// 该商品sku的应付价格 = 之前的应付价格 - 现在积分优惠的价格
					skuInfo.should_payment_amount -= skuInfo.integral_discount_amount;
					// 增加该商品sku的总优惠金额
					if (!skuInfo.total_discount) skuInfo.total_discount = 0;
					skuInfo.total_discount += skuInfo.integral_discount_amount;
					console.log(`sku[${skuInfo._id}]: 使用 ${skuInfo.used_integral} 积分优惠 ${vk.pubfn.toDecimal(skuInfo.integral_discount_amount/100,2)} 元`);
					sku_list[i] = skuInfo;
				}
			}
		} else {
			order_used_integral_key = false;
			integral_discount_amount = 0;
			used_integral = 0;
		}
		return {
			code: 0,
			msg: "ok",
			sku_list, // 积分优惠后的商品数据
			discount_amount: integral_discount_amount, // 积分抵扣金额
			used_integral, // 使用积分数量
			order_used_integral_key, // 是否使用 积分 优惠
		};
	},

	/**
	 * 获取订单详情
	 * @url client/order.getInfo 前端调用的url参数地址
	 */
	getInfo: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id,
			order_no,
			user
		} = data;
		let orderInfo;
		if (vk.pubfn.isNotNull(_id)) {
			orderInfo = await vk.daoCenter.orderDao.findById(_id);
		} else if (vk.pubfn.isNotNull(order_no)) {
			orderInfo = await vk.daoCenter.orderDao.findByOrderNo(order_no);
		} else {
			return { code: -1, msg: "订单号不能为空" };
		}
		if (vk.pubfn.isNull(orderInfo)) return { code: -2, msg: "订单不存在" };
		if (orderInfo.user_id !== uid && !userInfo.is_verify_staff) return { code: -1, msg: "您无权限查看该订单" };
		// 判断订单是否过期，如过期，则取消订单
		if (orderInfo.status === 0 && orderInfo.auto_cancel_time > 0 && Date.now() >= orderInfo.auto_cancel_time) {
			// 取消订单
			orderInfo = await vk.daoCenter.orderDao.cancelOrder({
				order_no,
				user_id: uid,
				author: "overtime"
			});
		}
		res.orderInfo = orderInfo;
		if (user) {
			res.userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		}
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 取消订单
	 * @url client/order.cancel 前端调用的url参数地址
	 */
	cancel: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			order_no,
			pwd
		} = data;
		if (vk.pubfn.isNull(order_no)) return { code: -1, msg: "订单号不能为空" };
		let orderInfo = await vk.daoCenter.orderDao.findByOrderNo(order_no);
		if (orderInfo.user_id !== uid) return { code: -1, msg: "您无权限操作该订单" };
		if (orderInfo.status !== 0) return { code: -1, msg: '该订单不可取消!' };
		orderInfo = await vk.daoCenter.orderDao.cancelOrder({
			order_no,
			user_id: uid,
			author: "my"
		});
		res.orderInfo = orderInfo;
		res.msg = "取消订单成功";
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 取消订单(给定时器使用)
	 * @url client/order.pub_cancel 前端调用的url参数地址
	 */
	pub_cancel: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			order_no,
			pwd
		} = data;
		if (pwd !== "%……&*#@！%￥）（*{}”“|”L》》《") return { code: -1, msg: "" };
		if (vk.pubfn.isNull(order_no)) return { code: -1, msg: "订单号不能为空" };
		let orderInfo = await vk.daoCenter.orderDao.findByOrderNo(order_no);
		if (orderInfo.status !== 0) return { code: -1, msg: '该订单不可取消!' };
		orderInfo = await vk.daoCenter.orderDao.cancelOrder({
			order_no,
			user_id: orderInfo.user_id,
			author: "system"
		});
		res.msg = "取消订单成功";
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我的订单列表
	 * @url client/order.getMyOrderList 前端调用的url参数地址
	 */
	getMyOrderList: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { formData = {} } = data;
		let {
			easy_status,
			order_type,
			searchvalue
		} = formData;
		let whereJson = {
			user_id: uid
		};
		if (vk.pubfn.isNotNull(easy_status)) {
			if (vk.pubfn.isNull(order_type)) {
				// 全部
				if (easy_status === 0) {
					whereJson["status"] = 0;
				} else if (easy_status === 1) {
					whereJson["status"] = _.in([1, 2, 3, 4, 5]);
				} else if (easy_status === 2) {
					whereJson["status"] = 5;
				} else if (easy_status === 3) {
					whereJson["status"] = 6;
				} else if (easy_status === 4) {
					whereJson["status"] = _.in([-2]);
				}
			} else if (order_type === 0) {
				// 电商订单（实物商品订单）
				if (easy_status === 0) {
					whereJson["status"] = 0;
				} else if (easy_status === 1) {
					whereJson["status"] = _.in([1, 2]);
				} else if (easy_status === 2) {
					whereJson["status"] = _.in([3, 4]);
				} else if (easy_status === 3) {
					whereJson["status"] = 5;
				} else if (easy_status === 4) {
					whereJson["status"] = _.in([-2]);
				}
			} else if (order_type === 1) {
				// 电子卡券订单（虚拟商品订单）
				if (easy_status === 0) {
					whereJson["status"] = 0;
				} else if (easy_status === 1) {
					whereJson["status"] = 4;
				} else if (easy_status === 2) {
					whereJson["status"] = _.in([5, 6]);
				} else if (easy_status === 3) {
					whereJson["status"] = -4;
				} else if (easy_status === 4) {
					whereJson["status"] = _.in([-2]);
				}
			}
		}
		res = await vk.daoCenter.orderDao.getTableData({
			data,
			whereJson
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 余额支付
	 * @url client/order.balancePay 前端调用的url参数地址
	 */
	balancePay: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id,
			used_balance,
		} = data;
		if (vk.pubfn.isNullOne(_id)) {
			return { code: -1, msg: '订单ID不能为空' };
		}
		// 余额支付
		res = await this._paySuccess({
			_id, // 订单id
			type: 0, // 0: 余额支付 1 线上第三方支付 2 线下支付
			checkLoginUser: true, // 用户信息，只在type=0时用到
			used_balance,
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单支付成功
	res = await this._paySuccess({
		order_no, // 订单号
		type: 1, // 0: 余额支付 1 线上第三方支付 2 线下支付
		checkLoginUser: true, // 是否需要检测当前登录用户和订单下单人是否匹配，只在type=0时用到
	});
	 */
	_paySuccess: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id, // 订单id（与order_no二选一）
			order_no: no, // 订单号（与_id二选一）
			type, // 0: 余额支付 1 线上第三方支付 2 线下支付
			checkLoginUser = true, // 是否需要检测当前登录用户和订单下单人是否匹配，只在type=0时用到
			used_balance, // 使用多少余额，只在type=0时用到
		} = data;
		// 参数合法判断开始-----------------------------------------------------------
		if (vk.pubfn.isNull(type)) return { code: -1, msg: "付款类型错误" };
		let orderInfo;
		if (vk.pubfn.isNotNull(_id)) {
			orderInfo = await vk.daoCenter.orderDao.findById(_id);
		} else if (vk.pubfn.isNotNull(no)) {
			orderInfo = await vk.daoCenter.orderDao.findByOrderNo(no);
		} else {
			return { code: -1, msg: "订单号不能为空" };
		}
		if (vk.pubfn.isNull(orderInfo)) return { code: -1, msg: "订单不存在" };
		let time = Date.now(); // 获取当前时间
		let {
			status, // 订单状态
			amount_info, // 金额信息
			discount_info, // 优惠信息
			order_no, // 订单号
		} = orderInfo;
		if (status !== 0) {
			return { code: -1, msg: '付款失败，该订单可能已付款或已取消!' };
		}
		let {
			need_payment_amount, // 订单还需支付金额
			express_amount, // 运费
		} = amount_info;
		if (need_payment_amount < 0 || express_amount < 0) {
			return { code: -1, msg: '订单金额异常' };
		}
		// 参数合法判断结束-----------------------------------------------------------
		let pay_type; // 订单支付方式 wxpay 微信 alipay 支付宝 balance 用户余额 offline 线下支付 none 无需支付
		let orderUpdateDataJson = {};
		let used_balance_amount; // 标记本次使用余额数量
		let current_payment_amount; // 标记本次支付金额
		let userInfo = await vk.daoCenter.userDao.findById(orderInfo.user_id); // 用户下单用户信息
		if (type === 0) {
			// 余额支付
			let { uid } = this.getClientInfo(); // 获取客户端信息
			if (vk.pubfn.isNull(userInfo)) return { code: -1, msg: "该订单异常：订单下单人不存在" };
			if (checkLoginUser && userInfo._id !== uid) return { code: -1, msg: "该订单不属于您，您无权操作" };
			// 获取用户余额
			let balance = this._getUserBalance(userInfo);
			if (!used_balance) used_balance = need_payment_amount; // 如果此值未传，则 = need_payment_amount
			// 判断余额是否足够支付订单金额（因为支持余额+第三方支付组合支付方式，故不需要判断余额是否足够）
			if (balance < used_balance) {
				return { code: -1, msg: `您的余额不足！\n您的余额剩余：${vk.pubfn.priceFilter(balance)}` };
			}
			used_balance_amount = used_balance; // 标记本次使用余额数量
			current_payment_amount = used_balance; // 标记本次支付金额
			// 计算余额抵扣的金额 开始-----------------------------------------------------------
			// 如果余额>运费,则不仅要抵扣运费,还要抵扣订单金额
			if (used_balance_amount > express_amount) {
				// 设置订单运费的余额使用量
				discount_info.balance_discount_express_amount = express_amount;
				// 设置订单金额(不含运费)的余额使用量
				discount_info.balance_discount_amount = used_balance_amount - express_amount;
			} else {
				// 如果余额<=运费，余额只抵扣运费
				discount_info.balance_discount_express_amount = used_balance_amount;
				discount_info.balance_discount_amount = 0;
			}
			// 记录订单共使用了多少的余额
			amount_info.used_balance_amount += used_balance_amount;
			// 记录订单已实付金额
			amount_info.payment_amount += used_balance_amount;
			// 订单还需要支付金额 = 订单应付金额 - 订单已实付金额
			amount_info.need_payment_amount = amount_info.should_payment_amount - amount_info.payment_amount;
			if (amount_info.need_payment_amount < 0) {
				return { code: -1, msg: '订单金额异常' };
			}
			// 计算余额抵扣的金额 结束-----------------------------------------------------------
			pay_type = "balance"; // 支付方式标记为余额支付
			orderUpdateDataJson = {
				"amount_info.payment_amount": amount_info.payment_amount, // 用户实际付款金额
				"amount_info.need_payment_amount": amount_info.need_payment_amount, // 用户还需要付款金额（通常为0）
				"amount_info.used_balance_amount": amount_info.used_balance_amount, // 用户使用多少余额
				"discount_info.balance_discount_express_amount": discount_info.balance_discount_express_amount, // 余额抵扣运费金额
				"discount_info.balance_discount_amount": discount_info.balance_discount_amount, // 余额抵扣订单金额
			}
		} else if (type === 1) {
			// 在线支付
			// 分微信和支付宝
			let payOrderInfo = await vk.daoCenter.payOrderDao.findByOutTradeNo(order_no); // 获取第三方支付订单
			if (payOrderInfo.status !== 1) {
				return { code: -1, msg: '订单异常：检测到订单未支付' };
			}
			if (payOrderInfo.pay_type.indexOf("wxpay_") === 0) {
				pay_type = "wxpay"; // 微信支付
			} else if (payOrderInfo.pay_type.indexOf("alipay_") === 0) {
				pay_type = "alipay"; // 支付宝支付
			}
			current_payment_amount = payOrderInfo.total_fee; // 标记本次支付金额
			amount_info.used_cash_amount += payOrderInfo.total_fee; // 设置用户使用现金金额
			amount_info.payment_amount += payOrderInfo.total_fee; // 设置订单已支付金额
			// 订单还需要支付金额 = 订单应付金额 - 订单已实付金额
			amount_info.need_payment_amount = amount_info.should_payment_amount - amount_info.payment_amount;
			orderUpdateDataJson = {
				"transaction_id": payOrderInfo.transaction_id, // 第三方支付交易单号
				"platform": payOrderInfo.platform, // 支付平台，如 h5、mp-weixin、mp-alipau、app-plus等
				"amount_info.payment_amount": amount_info.payment_amount, // 用户实际付款金额
				"amount_info.need_payment_amount": amount_info.need_payment_amount, // 用户还需要付款金额（通常为0）
				"amount_info.used_cash_amount": amount_info.used_cash_amount, // 订单使用现金付款金额
			}
		} else if (type === 2) {
			// 线下支付（算现金支付）
			pay_type = "offline";
			current_payment_amount = amount_info.need_payment_amount;
			amount_info.used_cash_amount += amount_info.need_payment_amount;
			amount_info.payment_amount += amount_info.need_payment_amount;
			// 订单还需要支付金额 = 订单应付金额 - 订单已实付金额
			amount_info.need_payment_amount = amount_info.should_payment_amount - amount_info.payment_amount;
			orderUpdateDataJson = {
				"amount_info.payment_amount": amount_info.payment_amount, // 用户实际付款金额
				"amount_info.need_payment_amount": amount_info.need_payment_amount, // 用户还需要付款金额（通常为0）
				"amount_info.used_cash_amount": amount_info.used_cash_amount, // 订单使用现金付款金额
			}
		} else {
			// 无支付方式（也可能是无需支付）
			pay_type = "none";
			current_payment_amount = 0;
			if (amount_info.need_payment_amount > 0) {
				// 此时可以发邮件通知系统管理员告知异常订单，因为正常来说，这里不会出异常。
				return { code: -1, msg: '订单金额异常' };
			}
		}

		// 开启事务，uniCloud事务自带锁，可以防止同一订单重复付款
		const transaction = await vk.baseDao.startTransaction();
		try {
			if (type === 0) {
				// 如果是余额支付，则需要扣余额
				// 先扣余额，扣除成功在修改订单状态
				let upReq = await vk.daoCenter.moneyDao.updateAccountBalanceForTransaction({
					db: transaction,
					user_id: userInfo._id,
					value: used_balance_amount,
					isAdd: false,
					no: order_no,
					title: `订单支付`,
					comment: ``,
					add_type: 3, // 消费
				});
				if (upReq.code !== 0) {
					//await transaction.rollback();
					return { code: -1, msg: upReq.msg };
				}
			}
			let { now } = vk.pubfn.getCommonTime(time);
			// 订单时间线
			let timeline = { time, msg: "用户付款", type: "pay", oper_type: "my", oper_uid: orderInfo.user_id, amount: current_payment_amount, pay_type };
			// 判断订单是否已全额支付
			let paySucceeded = amount_info.need_payment_amount > 0 ? false : true;
			if (!paySucceeded) {
				// 部分支付
				// 修改订单数据
				orderInfo = await vk.daoCenter.orderDao.updateAndReturn({
					db: transaction,
					whereJson: {
						_id: orderInfo._id,
						status: 0
					},
					dataJson: {
						...orderUpdateDataJson,
						timeline: _.push(timeline)
					}
				});
				if (!orderInfo) {
					throw new Error("msg:订单状态异常");
				}
				res.msg = `还需支付${vk.pubfn.priceFilter(amount_info.need_payment_amount)}`;
				console.log(`订单${orderInfo.order_no}${res.msg}`);
			} else {
				// 全额支付成功
				let mchInfo = await vk.daoCenter.mchDao.find();
				let planDay = vk.pubfn.getData(mchInfo, "fx.plan_exec_time", 0);
				let { todayStart } = vk.pubfn.getCommonTime();
				let plan_exec_time = vk.pubfn.getOffsetTime(todayStart, {
					day: planDay,
					mode: "after", // after 之后 before 之前
				});
				// 修改订单数据
				orderInfo = await vk.daoCenter.orderDao.updateAndReturn({
					db: transaction,
					whereJson: {
						_id: orderInfo._id,
						status: 0
					},
					dataJson: {
						...orderUpdateDataJson,
						status: 1, // 设置订单状态为已付款
						enable_delivery: true, // 标记订单可以发货
						pay_type, // 支付方式
						pay_time: time, // 付款时间
						date: now,
						timeline: _.push(timeline),
						"fx.plan_exec_time": plan_exec_time
					}
				});
				if (!orderInfo) {
					throw new Error("msg:订单状态异常");
				}
				// 如果是虚拟商品订单，则直接发货（注意：虚拟商品的核销码就是订单id）
				if (orderInfo.order_type === 1) {
					// 订单发货操作
					let orderSendRes = await vk.daoCenter.orderDao.orderSend({
						db: transaction,
						orderInfo, // 订单信息
						mchInfo, // 商家信息
					});
					if (orderSendRes.code === 0) {
						res.orderInfo = orderSendRes.orderInfo;
					}
				}
				if (orderInfo.amount_info.give_integral > 0) {
					// 添加积分
					await vk.daoCenter.moneyDao.updateAccountIntegralForTransaction({
						db: transaction,
						user_id: userInfo._id,
						value: orderInfo.amount_info.give_integral, // 此值始终为正整数 100=1元
						isAdd: true, // true 增加 false 减少
						no: orderInfo.order_no,
						title: `订单付款奖励积分`,
						comment: ``,
						add_type: 7, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
						updateTotal: true,
					});
				}
				// 写入任务执行表（用于异步计算奖励、业绩、发送短信等等）
				await vk.daoCenter.orderTaskDao.addOrderTask({
					db: transaction,
					dataJson: {
						type: 1001, // 1001 订单付款 1002 订单退款
						title: `订单【${order_no}】付款成功`,
						order_no, // 订单号
						plan_exec_time,
					}
				});
				res.msg = "支付成功";
				console.log(`订单${orderInfo.order_no}${res.msg}`);
			}
			res.code = 0; // 0代表成功
			res.orderNo = orderInfo.order_no; // 订单号
			res.orderId = orderInfo._id; // 订单id
			res.orderInfo = orderInfo; // 订单信息
			// 提交事务
			await transaction.commit();
			await vk.daoCenter.userDao.updateById({
				id: userInfo._id,
				dataJson: {
					buy: _.inc(1),
				},
			});
			if (paySucceeded) {
				// 添加SKU销量（不使用事务）防止写入冲突
				await vk.daoCenter.goodsDao.updateGoodsRealSellCountBySkuList(orderInfo.goods_sku_list);
			}
			console.log(`transaction succeeded`);
			return res;
		} catch (err) {
			// 事务回滚
			return await vk.baseDao.rollbackTransaction({
				db: transaction,
				err
			});
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单申请退款 退款申请
	 * @url client/order.applyRefund 前端调用的url参数地址
	 */
	applyRefund: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id, // 订单id
			refund_reason, // 退款原因
			refund_desc, // 退款说明（用户备注）
			images, // 用户上传的图片，如快递面单等
			goods_sku_list, // 退款商品数量
			express_name, // 寄回的快递公司名称
			express_no, // 寄回的快递公司单号
		} = data;
		let time = Date.now();
		if (vk.pubfn.isNull(_id)) {
			return { code: -1, msg: '订单ID不能为空' };
		}
		if (vk.pubfn.isNull(refund_reason)) {
			return { code: -1, msg: '退款原因不能为空' };
		}
		let orderInfo = await vk.daoCenter.orderDao.findById(_id);
		if (vk.pubfn.isNull(orderInfo)) {
			return { code: -1, msg: '订单信息不存在' };
		}
		if (orderInfo.user_id !== uid) {
			return { code: -1, msg: '该订单不是你的订单，无权操作！' };
		}
		if (orderInfo.is_not_refund) {
			return { code: -1, msg: '该订单不可申请退款！' };
		}
		let mchInfo = await vk.daoCenter.mchDao.find();
		let { status, amount_info, discount_info, order_no } = orderInfo;

		let errStatus = {
			"-4": "该订单已关闭，无法申请退款",
			"-3": "该订单已全额退款成功，请勿重复操作",
			"-2": "该订单已申请退款，请勿重复操作",
			"-1": "该订单已取消",
			"0": "该订单未付款",
			"2": "该订单已准备发货，暂不能申请退款，可联系客服处理。",
			"3": "该订单已发货，无法申请退款",
			"4": "该订单已发货，无法申请退款",
			"5": "该订单已完成，无法申请退款",
			"6": "该订单已完成，无法申请退款",
		};
		let refundStatus = vk.pubfn.getData(mchInfo, "order_refund.status", 0);
		let arr = [];
		if (refundStatus == 1) {
			arr = [1, 3, 4];
		} else if (refundStatus == 2) {
			arr = [1, 3, 4, 5];
		} else {
			arr = [1];
		}
		if (arr.indexOf(status) == -1) {
			let msg = errStatus[status] || "该订单状态异常，无法申请退款"
			return { code: -1, msg };
		}

		// 判断是否满足自动审核条件
		let is_auto_refund = 0;
		if (orderInfo.status === 1) {
			// 只有订单状态为已付款且未发货，才能自动退款
			let max_amount = vk.pubfn.getData(mchInfo, "order_refund.max_amount");
			let max_month_count = vk.pubfn.getData(mchInfo, "order_refund.max_month_count");
			let nin_goods_ids = vk.pubfn.getData(mchInfo, "order_refund.nin_goods_ids");
			let autoRefundLog = {
				max_amount,
				max_month_count,
				nin_goods_ids
			};
			// 如果全部为空，则不进行自动退款
			if (vk.pubfn.isNull(max_amount) && vk.pubfn.isNull(max_month_count) && vk.pubfn.isNull(nin_goods_ids)) {
				is_auto_refund = 0;
			} else {
				let { monthStart, monthEnd } = vk.pubfn.getCommonTime();

				let is_max_amount = true;
				let is_max_month_count = true;
				let is_nin_goods_ids = true;

				if (vk.pubfn.isNotNull(max_amount)) {
					if (orderInfo.amount_info.payment_amount >= max_amount) {
						is_max_amount = false;
					}
					autoRefundLog.payment_amount = orderInfo.amount_info.payment_amount;
				}
				if (vk.pubfn.isNotNull(max_month_count)) {
					let count = await vk.daoCenter.orderDao.count({
						user_id: uid,
						status: _.in([-4, -3, -2]),
						refund_time: _.gte(monthStart).lte(monthEnd)
					});
					if (count >= max_month_count) {
						is_max_month_count = false;
					}
					autoRefundLog.count = count;
				}
				if (vk.pubfn.isNotNull(nin_goods_ids)) {
					// 检查该订单是否包含这些商品中任意一个
					nin_goods_ids.map((item, index) => {
						let goodsInfo = vk.pubfn.getListItem(orderInfo.goods_sku_list, "goods_id", item);
						if (goodsInfo) {
							is_nin_goods_ids = false;
							autoRefundLog.goods_id = goodsInfo.goods_id;
						}
					});
				}

				if (is_max_amount && is_max_month_count && is_nin_goods_ids) {
					is_auto_refund = 1;
				}
			}
			console.log(`订单${is_auto_refund == 1 ? '' : '不'}满足自动退款条件`, autoRefundLog);
		}

		let applyRefundRes = await vk.daoCenter.orderDao.applyRefund({
			mchInfo,
			orderInfo,
			oper_type: "my",
			oper_uid: uid,
			refund_reason,
			refund_desc,
			images,
			goods_sku_list,
			express_name,
			express_no,
			is_auto_refund
		});
		if (applyRefundRes.code !== 0) return applyRefundRes;
		res.msg = applyRefundRes.msg;
		res.orderInfo = applyRefundRes.orderInfo;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单取消退款
	 * @url client/order.cancelRefund 前端调用的url参数地址
	 */
	cancelRefund: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id
		} = data;
		let time = Date.now();
		if (vk.pubfn.isNull(_id)) {
			return { code: -1, msg: '订单ID不能为空' };
		}
		let orderInfo = await vk.daoCenter.orderDao.findById(_id);
		if (vk.pubfn.isNull(orderInfo)) {
			return { code: -1, msg: '订单信息不存在' };
		}
		if (orderInfo.user_id !== uid) {
			return { code: -1, msg: '该订单不是你的订单，无权操作！' };
		}
		let { status } = orderInfo;
		if (status !== -2) {
			return { code: -1, msg: '该订单未申请退款!' };
		}
		// 订单取消退款
		let newOrderInfo = await vk.daoCenter.orderDao.cancelRefund({
			orderInfo,
			author: "my"
		});
		if (!newOrderInfo) return { code: -1, msg: '取消退款失败！' };
		res.orderInfo = newOrderInfo;
		res.msg = "已取消退款申请，订单将会正常发货！";
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 创建第三方支付订单（商品订单）
	 * @url client/order.createPaymentForGoods 前端调用的url参数地址
	 */
	createPaymentForGoods: async function(data) {
		let { uid, platform } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			provider,
			openid,
			out_trade_no,
			isPC,
			return_url
		} = data;
		let type = "goods"; // 固定为goods 代表商品订单
		// 如果是商品订单，则需要查询订单是否已下单且在待付款状态
		let orderInfo = await vk.daoCenter.orderDao.findByOrderNo(out_trade_no);
		if (!orderInfo) return { code: -1, msg: "订单不存在" };
		if (orderInfo.status !== 0) return { code: -1, msg: "订单已付款或已取消" };
		let total_fee = orderInfo.amount_info.need_payment_amount; // 订单金额(单位分 100 = 1元)
		let subject = "商品订单";
		let provider_pay_method = provider;
		// 获取支付渠道
		if (useVkspayPlatformList.indexOf(platform) > -1) {
			provider = "vkspay";
		}
		// 发起支付
		res = await vk.vkPay.createPayment({
			context: this.getClientInfo(),
			provider,
			isPC,
			data: {
				openid,
				out_trade_no,
				total_fee, // 订单金额(单位分 100 = 1元)
				subject,
				type,
				user_id: uid, // 用户id
				return_url, // 同步回调地址，仅vkspay生效（选填）
				// 自定义数据，不可与外部重复（custom内的参数不会发送给微信、支付宝）
				custom: {

				},
				// 微信、支付宝文档上的其他选填参数（other内的参数会原样发送给微信、支付宝）
				other: {

				}
			}
		});
		res.provider_pay_method = provider_pay_method;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 创建第三方支付订单（余额充值）
	 * @url client/order.createPaymentForBalanceRecharge 前端调用的url参数地址
	 */
	createPaymentForBalanceRecharge: async function(data) {
		let { uid, platform } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			provider,
			openid,
			isPC,
			type,
			total_fee, // 金额
			return_url,
		} = data;
		if (!type) type = "goods";
		// 自动创建一个订单号（订单号理论上会重复，但概率非常非常低，就算重复了，数据不会入库（唯一索引）
		let out_trade_no = vk.pubfn.createOrderNo("CZ");
		// 创建充值订单
		let orderId = await vk.daoCenter.orderRechargeDao.addOrder({
			userInfo,
			order_no: out_trade_no, // 订单号
			payment_amount: total_fee, // 付款金额
			recharge_balance: total_fee, // 余额数量 = 付款金额
			order_type: 0, // 0 余额充值（暂只支持余额充值）
		});
		if (!orderId) return { code: -1, msg: "操作失败，请重试！" };

		let subject = "余额充值";
		let provider_pay_method = provider;
		// 获取支付渠道
		if (useVkspayPlatformList.indexOf(platform) > -1) {
			provider = "vkspay";
		}
		// 发起支付
		res = await vk.vkPay.createPayment({
			context: this.getClientInfo(),
			provider,
			isPC,
			data: {
				openid,
				out_trade_no,
				total_fee, // 订单金额(单位分 100 = 1元)
				subject,
				type,
				return_url, // 同步回调地址，仅vkspay生效（选填）
				// 自定义数据，不可与外部重复（custom内的参数不会发送给微信、支付宝）
				custom: {
					user_id: uid, // 用户id
					recharge_balance: total_fee, // 余额充值金额
				},
				// 微信、支付宝文档上的其他选填参数（other内的参数会原样发送给微信、支付宝）
				other: {

				}
			}
		});
		res.provider_pay_method = provider_pay_method;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 第三方支付订单状态查询
	 * @url client/order.queryPayment 前端调用的url参数地址
	 */
	queryPayment: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			out_trade_no
		} = data;
		res = await vk.vkPay.queryPayment({
			out_trade_no: data.out_trade_no, // 订单号
			await_notify: true, // 是否需要等待异步通知执行完成，若为了响应速度，可以设置为false，若需要等待异步回调执行完成，则设置为true
			pay_order_info: false, // 是否需要返回支付订单信息，默认为false
		});
		if (res.code === 0) {
			res.orderInfo = await vk.daoCenter.orderDao.findByOrderNo(out_trade_no);
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 第三方支付回调通知（商品订单付款回调）
	 * @url client/order.pub_payNotifyForGoods 前端调用的url参数地址
	 */
	pub_payNotifyForGoods: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			encryptedData
		} = data;
		// 解密 sessionKey 示例
		console.log('解密前: ', encryptedData)
		let decryptedRes = vk.vkPay.crypto.aes.decrypt({
			data: encryptedData, // 待解密的原文
		});
		console.log('解密后: ', decryptedRes)
		let {
			order_no,
		} = decryptedRes;
		if (vk.pubfn.isNullOne(order_no)) return { code: -1, msg: '订单号不能为空' };
		res = await this._paySuccess({
			order_no, // 订单号
			type: 1, // 0: 余额支付 1 线上第三方支付 2 线下支付
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 第三方支付回调通知（余额充值回调）
	 * @url client/order.pub_payNotifyForBalanceRecharge 前端调用的url参数地址
	 */
	pub_payNotifyForBalanceRecharge: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			encryptedData
		} = data;
		// 解密 sessionKey 示例
		console.log('解密前: ', encryptedData)
		if (vk.pubfn.isNull(encryptedData)) return { code: -1, msg: 'encryptedData不能为空' };
		let decryptedRes = vk.vkPay.crypto.aes.decrypt({
			data: encryptedData, // 待解密的原文
		});
		console.log('解密后: ', decryptedRes)
		let {
			order_no,
		} = decryptedRes;
		if (vk.pubfn.isNull(order_no)) return { code: -1, msg: '订单号不能为空' };
		// 获取第三方支付订单信息
		let payOrderInfo = await vk.daoCenter.payOrderDao.findByOutTradeNo(order_no);
		if (vk.pubfn.isNull(payOrderInfo)) return { code: -1, msg: '订单不能为空' };
		// 获取充值订单信息
		let orderInfo = await vk.daoCenter.orderRechargeDao.findByOrderNo(order_no);
		if (vk.pubfn.isNull(orderInfo)) return { code: -1, msg: '订单不能为空' };
		if (orderInfo.status !== 0) return { code: -1, msg: '订单已付款或已取消' };
		let pay_type;
		if (payOrderInfo.pay_type.indexOf("wxpay") > -1) {
			pay_type = "wxpay";
		} else if (payOrderInfo.pay_type.indexOf("alipay") > -1) {
			pay_type = "alipay";
		}
		// 修改充值订单状态为已付款
		orderInfo = await vk.daoCenter.orderRechargeDao.orderPay({
			order_no,
			transaction_id: payOrderInfo.transaction_id,
			platform: payOrderInfo.platform,
			pay_type,
		});
		if (vk.pubfn.isNull(orderInfo)) return { code: -1, msg: "订单已付款或已取消" };
		if (orderInfo.order_type == 0) {
			// 余额充值
			let {
				user_id,
				recharge_balance
			} = orderInfo;
			// 开启事务
			const transaction = await vk.baseDao.startTransaction();
			try {
				// 给该用户添加余额
				await vk.daoCenter.moneyDao.updateAccountBalanceForTransaction({
					db: transaction,
					user_id,
					value: recharge_balance, // 此值始终为正整数 100=1元
					isAdd: true, // true 增加 false 减少
					no: order_no,
					title: `充值`,
					comment: ``,
					add_type: 2, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
					updateTotal: true,
				});
				// 提交事务
				await transaction.commit();
				console.log(`transaction succeeded`);
			} catch (err) {
				// 事务回滚
				return await vk.baseDao.rollbackTransaction({
					db: transaction,
					err
				});
			}
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取购物车
	 * @url client/order.getCart 前端调用的url参数地址
	 */
	getCart: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res.list = await vk.daoCenter.cartDao.listByUserId(uid);
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 更新购物车（直接覆盖）
	 * @url client/order.setCart 前端调用的url参数地址
	 */
	setCart: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			list
		} = data;
		await vk.daoCenter.cartDao.setCart(uid, list);
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	// 获取用户余额
	_getUserBalance(userInfo) {
		return vk.pubfn.getData(userInfo, "account_balance.balance", 0);
	},
	/**
	 * 用户确认收货
	 * @url client/order.confirmReceipt 前端调用的url参数地址
	 */
	confirmReceipt: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id
		} = data;
		// 参数非空检测
		if (vk.pubfn.isNull(_id)) {
			return { code: -1, msg: 'id不能为空' };
		}
		let time = Date.now();
		let mchInfo = await vk.daoCenter.mchDao.find();
		let day = vk.pubfn.getData(mchInfo, "order.auto_complete", 7);
		let auto_complete_time = time + 1000 * 3600 * 24 * day; // X天后自动完成
		// 订单时间线
		let timeline = { time, msg: "用户确认收货", type: "confirmReceipt", oper_type: "my", oper_uid: uid };
		res.info = await vk.daoCenter.orderDao.updateAndReturn({
			whereJson: {
				_id,
				user_id: uid, // 只能操作自己的订单
				status: 4, // 只有已全部发货的订单才可以确认收货
				order_type: 0, // 只有电商订单才可以确认收货
			},
			dataJson: {
				status: 5,
				confirm_receive_time: time,
				auto_complete_time,
				timeline: _.push(timeline)
			}
		});
		if (!res.info) {
			return { code: -1, msg: "确认收货失败，订单不满足确认收货条件。" };
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单评价
	 * @url client/order.addComment 前端调用的url参数地址
	 */
	addComment: async function(data) {
		let { uid, clientIP } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id,
			list = []
		} = data;
		if (vk.pubfn.isNull(_id)) return { code: -1, msg: "id不能为空" };
		let orderInfo = await vk.daoCenter.orderDao.findById(_id);
		if (vk.pubfn.isNull(orderInfo)) return { code: -1, msg: "订单不存在" };
		if (orderInfo.status === 6) return { code: -1, msg: "该订单已评价，请勿重复操作。" };
		if (orderInfo.status !== 5) return { code: -1, msg: "该订单暂不可评价" };
		if (orderInfo.user_id !== uid) return { code: -1, msg: "你无权操作该订单" };

		let dataArr = [];
		let errMsg;
		for (let i = 0; i < orderInfo.goods_sku_list.length; i++) {
			let item1 = orderInfo.goods_sku_list[i];
			let item2 = vk.pubfn.getListItem(list, "sku_id", item1._id);
			if (vk.pubfn.isNull(item2)) {
				errMsg = "参数错误";
				break;
			}
			dataArr.push({
				status: 0,
				goods_id: item1.goods_id,
				goods_name: item1.goods_name,
				sku_id: item1.sku_id,
				sku_name: item1.sku_name,
				buy_num: item1.buy_num,
				stars: item2.stars,
				content: item2.content,
				images: item2.images,
				user_id: uid,
				user_info: {
					nickname: userInfo.nickname,
					avatar: userInfo.avatar
				},
				publish_ip: clientIP
			});
		}
		if (errMsg) return { code: -1, msg: errMsg };

		// 添加评价
		await vk.daoCenter.goodsCommentDao.adds(dataArr);
		// 标记订单为已评价
		let time = Date.now();
		// 订单时间线
		let timeline = { time, msg: "用户进行评价", type: "comment", oper_type: "my", oper_uid: uid };
		res.info = await vk.daoCenter.orderDao.updateAndReturn({
			whereJson: {
				_id,
				user_id: uid,
				status: 5, // 只有已确认收货的订单才可以评价
			},
			dataJson: {
				status: 6,
				complete_time: time,
				timeline: _.push(timeline)
			}
		});
		// 无需添加对应的商品评价数量，因为只有等审核通过的评价才会计入。
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单核销
	 * @url client/order.orderVerify 前端调用的url参数地址
	 */
	orderVerify: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id, // 订单id
			num, // 核销数量
		} = data;
		// 参数非空检测
		let nullKey = vk.pubfn.isNullOneByObject({ _id, num });
		if (nullKey) return { code: -1, msg: '参数 ' + nullKey + ' 不能为空' };
		// 获取订单信息
		let orderInfo = await vk.daoCenter.orderDao.findById(_id);
		if (vk.pubfn.isNull(orderInfo)) return { code: -1, msg: "订单信息错误" };
		if (orderInfo.status <= 0) return { code: -1, msg: "该订单未付款" };
		if (orderInfo.order_type !== 1) return { code: -1, msg: "该订单状态不支持核销" };
		if (orderInfo.user_id !== uid && !userInfo.is_verify_staff) return { code: -1, msg: "你无权操作该订单" };

		let time = Date.now();
		// 订单时间线
		let timeline = { time, msg: `订单核销（数量：${num}）`, type: "verify", oper_type: "business", oper_uid: uid, num, oper_nickname: userInfo.nickname };
		// 设置核销数量
		let { verify_num = 0, buy_num = 0, refund_num = 0, verify_start_time, verify_exp_time } = orderInfo.goods_sku_list[0];

		if (verify_start_time > 0 && verify_start_time > time) {
			return { code: -1, msg: `请在${vk.pubfn.timeFormat(verify_start_time)}之后再使用。` };
		} else if (verify_exp_time > 0 && time > verify_exp_time) {
			return { code: -1, msg: `已过期，最晚核销时间：${vk.pubfn.timeFormat(verify_exp_time)}` };
		}

		let maxNum = buy_num - refund_num;
		verify_num += num;
		if (verify_num > maxNum) return { code: -1, msg: `核销数量错误，已超过最大核销数量${maxNum}` };
		orderInfo.goods_sku_list[0].verify_num = verify_num;
		let dataJson = {
			goods_sku_list: _.set(orderInfo.goods_sku_list), // 更新商品核销数据
			timeline: _.push(timeline)
		};
		if (verify_num === maxNum) {
			// 标记为已全部核销完
			dataJson["status"] = 5;
		}
		res.orderInfo = await vk.daoCenter.orderDao.updateAndReturn({
			db,
			whereJson: {
				_id: orderInfo._id
			},
			dataJson
		});
		res.msg = `已成功核销${num}个商品`;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 模板函数
	 * @url client/order.test 前端调用的url参数地址
	 */
	test: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------


		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
};

module.exports = cloudObject;
